/*
 * Copyright (c) 2016-2021, Hangzhou Qulian Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _ACCOUNT_H_
#define _ACCOUNT_H_

#include <string.h>
#include "ql_type.h"
#include "log.h"
#include "x509.h"
#include "keccak256.h"
#include "ecc.h"
#include "json.h"
#include "ql_error_type.h"
#include "math.h"
// [1k] space is allocated here to cache the original transaction information, which will be used to
// calculate the keccak hash. If the space is not enough, please make changes according to actual needs
#define MAX_BUF_SPACE_SIZE 1024

// ----------------------------------------------
// Error type definition
// ----------------------------------------------
#define ACCOUNT_SUCCESS               (ERR_ACCOUNT_BASE + 0)  // Success
#define ACCOUNT_ERR_PARAM_INVAILD    -(ERR_ACCOUNT_BASE + 1)  // Invalid argument
#define ACCOUNT_ERR_CALLOC_MEMORY    -(ERR_ACCOUNT_BASE + 2)  // Failed to apply for memory
#define ACCOUNT_ERR_GETTIME_FUNC     -(ERR_ACCOUNT_BASE + 3)  // Get the timesTamp method error
#define ACCOUNT_ERR_OVER_MAX_SIZE    -(ERR_ACCOUNT_BASE + 4)  // Space > MAX_BUF_SPACE_SIZE
#define ACCOUNT_ERR_BUF_TOO_SMALL    -(ERR_ACCOUNT_BASE + 5)  // Too little space
#define ACCOUNT_ERR_VER_UNMATCH      -(ERR_ACCOUNT_BASE + 6)  // Incompatible version
#define ACCOUNT_ERR_ALGO_UNMATCH     -(ERR_ACCOUNT_BASE + 7)  // Incompatible algo
#define ACCOUNT_ERR_PRIKEY_UNMATCH   -(ERR_ACCOUNT_BASE + 8)  // Incompatible priKey
#define ACCOUNT_ERR_PUBKEY_UNMATCH   -(ERR_ACCOUNT_BASE + 9)  // Incompatible pubKey
#define ACCOUNT_ERR_ADDR_UNMATCH     -(ERR_ACCOUNT_BASE + 10) // Incompatible address
// ----------------------------------------------
// tx type definition
// ----------------------------------------------
#define TX_TYPE_SENDTRANSACTION   (OhByteType*)("tx_sendTransaction")
#define TX_TYPE_UPLOAD            (OhByteType*)("fm_upload")
#define TX_TYPE_DOWNLOAD          (OhByteType*)("fm_download")
// ----------------------------------------------
// format message type
// ----------------------------------------------
typedef enum FormatType{ 
		ORIGIN_MSG,				// do not encapsulate message
		ADD_HTTP_BODY,			// add ORIGIN_MSG to the http body
        ADD_CURL_BODY,          // add ORIGIN_MSG to the curl body
} FormatType;
// ----------------------------------------------
// type definition
// ----------------------------------------------
// -- account data structure --
typedef struct {
    OhByteType   priKey[32];       // private key, hex format.
    OhByteType   pubKey[65];       // public  key, hex format.
    OhByteType   addr[43];         // address, string format.
} AccountType;
// -- tx data structure --
typedef struct {
    OhByteType   from[43];         // string format.
    OhByteType   to[43];           // string format.
    OhInt32Type  value;            // int format.
    OhByteType   signature[133];   // string format.
    OhInt64Type  timesTamp;        // int format.
    OhByteType   simulate[6];      // string format.
    OhInt64Type  nonce;            // int format.
    OhByteType   type[4];          // string format.
    OhByteType*  extra;
    OhByteType*  extraid;
} TxType;


#ifdef __cplusplus
extern "C"
{
#endif

/*
 GetTime function should fill the timesTamp into p_dest, the unit is ns.
 It should return ACCOUNT_SUCCESS if p_dest was filled.
*/
typedef OhErrType (*AccountGetTimeFunction)(OhInt64Type* p_dest);

/*
 Set the function that will be used to generate timesTamp.
 */
OhVoidType AccountSetTimeFunc(AccountGetTimeFunction p_t);

/*
 Initialize account by x509 certificate.
 Inputs:
    str  - Private key certificate. string format.
 Outputs:
    acc - Account object.
 */
OhErrType AccountInitX509(AccountType* acc, OhByteType* str);

/*
 Initialize account by json account.
 Inputs:
    str  - json account. string format.
 Outputs:
    acc - Account object.
 */
OhErrType AccountInitJson(AccountType* acc, OhByteType* str);

/*
 Initialize the transfer transaction.
 Inputs:
    acc - The account that issued this transaction.
    to - The destination address of the transaction. string format. <contain 0x>
    val - Transfer amount.
    ex - Deposit information.
 Outputs:
    tx - Transaction object.
 */
OhErrType TxSendNew(TxType* tx, AccountType* acc, OhByteType* to, OhInt32Type val, OhByteType* ex, OhByteType* exid);

/*
 Format the transaction to [buf]
 Inputs:
    tx - Transaction object.
    fmtType - encapsulate message type
    method - Transaction type.
    outBufLen - Buffer size.
 Outputs:
    outBuf - Format string buffer.
 */
OhErrType TxPrint(TxType* tx, FormatType fmtType, OhByteType* method, OhByteType* outBuf, OhSizeType outBufLen);


#ifdef __cplusplus
}
#endif

#endif
